package chapter2;

import lombok.extern.slf4j.Slf4j;

/**
 * @author caiya
 * @date 2020/3/14 12:34
 */
@Slf4j
public class SynchronizedTest {
    public static void main(String[] args) throws InterruptedException {
        /**
         * synchronized：内置锁，又叫监视器锁
         * 1、synchronized 作用：
         *      1）解决内存可见性问题
         *      2）解决原子性问题
         *
         * volatile：只能保证内存可见性、禁止重排序，不能保证操作的原子性，本质上使用的是非阻塞算法实现的
         * 2、什么时候使用 volatile：
         *      1）写入变量值不依赖变量的当前值，即 set 的时候，set 内部是不需要重新获取 set 的对象的值的，否则就是 读取->计算->写入 三部操作，就不能够保证原子性
         *      2）读写变量值时没有加锁，因为加了锁之后使用 volatile 就是多余了
         */
        ThreadNotSafeInteger threadNotSafeInteger = new ThreadNotSafeInteger();

        // 测试ThreadNotSafeInteger
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int value = threadNotSafeInteger.getValue();
                ++value;
                threadNotSafeInteger.setValue(value);
            }
        });
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                int value = threadNotSafeInteger.getValue();
                ++value;
                threadNotSafeInteger.setValue(value);
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                int value = threadNotSafeInteger.getValue();
                ++value;
                threadNotSafeInteger.setValue(value);
            }
        });

        thread.start();
        thread1.start();
        thread2.start();

        Thread.sleep(100);
        log.debug(String.valueOf(threadNotSafeInteger.getValue()));
    }

    /**
     * 线程安全类
     */
    static class ThreadSafeInteger {
        private int value;
        public synchronized int getValue() {
            return value;
        }
        public synchronized void setValue(int value) {
            this.value = value;
        }
    }

    /**
     * 线程不安全类
     */
    static class ThreadNotSafeInteger {
        private int value;
        public int getValue() {
            return value;
        }
        public void setValue(int value) {
            this.value = value;
        }
    }

    /**
     * 线程安全类
     */
    static class AnotherThreadSafeInteger {
        private volatile int value;
        public int getValue() {
            return value;
        }
        public void setValue(int value) {
            this.value = value;
        }
    }

}
